package main

import (
	"fmt"
	"math"
	"os"
	"sync"
	"text/tabwriter"
	"time"
)

func main()  {
	//保护程序临界区中的一种方式，提供了一种安全的方式来访问临界区
	//临界区是程序中需要独占访问共享资源的区域
	//channel通过通信共享内存，Mutex通过开发人员的约定同步访问共享内存
	//可以通过使用Mutex对内存进行保护来协调对内存的访问

	//两个goroutine试图增加和减少一个共同的值，使用Mutex互斥锁来同步访问：

	var count int
	var lock sync.Mutex
	var arithmetic sync.WaitGroup
	increment := func() {
		lock.Lock()
		defer lock.Unlock()
		count++
		fmt.Printf("Incrementinf:%d\n",count)
	}

	decrement := func() {
		lock.Lock()    //请求对临界区独占(计数器)，使用互斥锁来解决
		defer lock.Unlock()    //指出已经完成对临界区锁定的保护
		count--
		fmt.Printf("Decrementing: %d\n",count)
	}

	//增量
	for i := 0;i <= 5;i++ {
		arithmetic.Add(1)
		go func() {
			defer arithmetic.Done()
			decrement()
		}()
	}

	//减量
	for i := 0;i <= 5;i++ {
		arithmetic.Add(1)
		go func() {
			defer arithmetic.Done()
			decrement()
		}()
	}

	arithmetic.Wait()
	fmt.Println("Arithmetic complete.")



	//不同类型的互斥对象   sync.RWMutex
	//RWMutex对内存有着更多的控制，如读锁，写锁
	producer := func(wg *sync.WaitGroup,l sync.Locker) {   //l参数是sync.Locker类型，接口方法Lock和Unclock分别对应Mutex和RWMutex
		defer wg.Done()
		for i := 5;i>0;i-- {
			l.Lock()
			l.Unlock()
			time.Sleep(1)  //让producer等待1s，使其比观察者goroutines更不活跃
		}
	}

	observer := func(wg *sync.WaitGroup,l sync.Locker) {
		defer wg.Done()
		l.Lock()
		defer l.Unlock()
	}

	test := func(count int,mutex,rwMutex sync.Locker) time.Duretion {
		var wg sync.WaitGroup
		wg.Add(count+1)
		beginTestTime := timeNow()
		go producer(&wg,mutex)
		for i:=count;i>0;i-- {
			go observer(&wg,rwMutex)
		}
		wg.Wait()
		return time.Since(beginTestTime)
	}

	tw := tabwriter.NewWriter(os.Stdout,0,1,2,' ',0)
	defer tw.Flush()

	var m sync.RWMutex
	fmt.Fprintf(tw, "Readers\ttRWMutext\tMutext\n")
	for i:=0;i<20;i++ {
		count := int(math.Pow(2,float64(i)))
		fmt.Fprintf(
			tw,
			"%d\t%v\t%v\n",
			count,
			test(count,&m,m.Rlocker()),
			test(count,&m,&m),
		)
	}







}




